Skip to content

feat(generator): docs_kit:page + Registry v2 — one-line page registration - #29

Merged
mhenrixon merged 1 commit into
mainfrom
issue-13-docs-kit-page-generator
Jul 3, 2026
Merged

feat(generator): docs_kit:page + Registry v2 — one-line page registration#29
mhenrixon merged 1 commit into
mainfrom
issue-13-docs-kit-page-generator

Conversation

@mhenrixon

@mhenrixon mhenrixon commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Closes #12
Closes #13.

Also lands #12 (Registry v2), which #13 depends on — the generator injects the page "Title", group: "…" line that #12 introduces, so they ship together.

Why

Adding a docs page today is quadruple bookkeeping: an 8-line module Views; module Docs; module Pages nesting ceremony, a class body, AND a registry line whose four strings must match the class — forget either half and you silently get a missing page. This is the moment a developer decides documentation is too much work.

After this PR, adding a page is one command plus writing content:

rails g docs_kit:page "Getting Started" --group=Guide

What changed

Registry v2 (#12)

  • DocsKit::Registry gains an opt-in page(title, group:, slug:, view:, icon:) DSL with path_prefix / view_namespace. slug/view derive from the title (parameterize / camelize), both overridable per line. A default Entry gives readers + href + view_class (safe_constantize under view_namespace, nil until authored — no dead links). nav_items returns { group => [NavItem] } for authored pages only — the transform every site used to hand-write. Mixing page and entries raises Registry::Error.
  • Configuration#nav_registries (default {}): nav_groups derives the whole sidebar from it (dropping empty groups). An explicit c.nav lambda still wins — full backwards compatibility.
  • The gem requires the ActiveSupport inflections core-ext so it derives slugs/views standalone (a host app already has it).

Page generator (#13)

  • lib/generators/docs_kit/page/ writes the page in the compact class form (class Views::Docs::Pages::X < DocsUI::Page) — Zeitwerk resolves it through the directory-implied namespaces, killing the nesting tax — with a starter DocsUI::Section + Markdown island.
  • Injects page "Title", group: "Group" after the last page line, so ordering lands at the group's end.
  • --slug / --view / --eyebrow / --registry override every derivation.
  • Idempotent: no duplicate registry line, no clobbered file in --skip mode.
  • A legacy hash-entries registry is left untouched — the generator writes the page but prints the entry to add by hand rather than corrupting the array.

Install path + dogfood + docs

  • Install templates (doc.rb.erb, docs_kit.rb.erb, installation_page.rb.erb) rewritten to the v2 page DSL + nav_registries + compact class, so install output matches generator output.
  • Dogfood Doc + initializer converted to v2. Three titles that don't derive cleanly (Authoring pagesauthoring/Authoring, Styling & CSSstyling/Styling, Code languageslanguages/Languages) keep explicit slug:/view: overrides so URLs and view classes are preserved. Sidebar is byte-identical before/after.
  • README: Configure now leads with nav_registries (the custom lambda demoted to an "advanced" subsection); a new "Add a page" section leads with the generator and reframes hand-authoring as "under the hood". The dogfood authoring page does the same.

Test plan

  • spec/docs_kit/registry_spec.rb — page derivation + overrides; all/grouped over page entries; view_class resolution under view_namespace; href; icon; nav_items (authored-only, hrefs/icons); view_namespace-unset → all unauthored; mixed-mode raises.
  • spec/docs_kit/configuration_spec.rbnav_registries default/override; nav_groups derivation; empty-group drop; explicit-nav-wins; empty fallback.
  • spec/generators/page_generator_spec.rb — compact class + correct constants; v2 injection + ordering; --slug/--view/--eyebrow/--registry; legacy no-mutation; idempotent re-run + no file clobber.
  • Configuration + Registry at 100% line coverage.

Verification

  • bundle exec rake — rspec 153 examples, 0 failures + rubocop clean
  • Dogfood smoke: rails g docs_kit:page "Smoke Test" --group=Guide → page renders at /docs/smoke-test, appears in sidebar (verified end-to-end over HTTP); reverted.
  • All existing dogfood pages render 200 with the derived sidebar; every URL preserved.
  • Backwards compatible: the legacy hash-entries API and explicit c.nav lambda both still work.

…tion

## Summary

Adds `rails g docs_kit:page "Title" --group=Guide`, which scaffolds a docs
page's class AND its registry line in one command — the unit of work for "add a
page" drops to one shell command plus writing content. This required Registry v2
(the `page` DSL the generator injects), so both land together (closes #12, #13).

### Registry v2 (#12)
- `DocsKit::Registry` gains an opt-in declarative schema: `page(title, group:,
  slug:, view:, icon:)` with `path_prefix`/`view_namespace`. slug/view derive
  from the title (parameterize / camelize), both overridable. A default `Entry`
  gives readers + `href` + `view_class` (safe_constantize under view_namespace,
  nil until authored). `nav_items` returns `{ group => [NavItem] }` for authored
  pages only — the transform every site hand-wrote. Mixing `page` and `entries`
  raises a clear error.
- `Configuration#nav_registries` (default `{}`): `nav_groups` derives the whole
  sidebar from it, dropping empty groups. An explicit `c.nav` lambda still wins
  (full backwards compatibility).
- Requires the ActiveSupport inflections core-ext so the gem derives slugs/views
  standalone (a host app already has it).

### Page generator (#13)
- `lib/generators/docs_kit/page/` writes the page in the compact class form
  (`class Views::Docs::Pages::X < DocsUI::Page`) — Zeitwerk resolves it through
  the directory-implied namespaces, killing the 8-line nesting tax. Injects
  `page "Title", group: "Group"` after the last `page` line so ordering lands at
  the group's end. `--slug/--view/--eyebrow/--registry` override every
  derivation. Idempotent (no duplicate line, no file clobber in --skip). A
  legacy hash-`entries` registry is left untouched with a by-hand instruction
  printed instead of corrupting it.

### Install path + dogfood + docs
- Install templates (`doc.rb.erb`, `docs_kit.rb.erb`, `installation_page.rb.erb`)
  rewritten to the v2 `page` DSL + `nav_registries` + compact class, so install
  output matches generator output.
- Dogfood `Doc` + initializer converted to v2 (overrides preserve the three
  slugs/views that don't derive cleanly); sidebar byte-identical before/after.
- README: Configure leads with `nav_registries` (custom lambda demoted to
  advanced); new "Add a page" section leads with the generator. Dogfood
  authoring page leads with the one-command flow, hand-authoring as "under the
  hood".

## Test Coverage
- spec/docs_kit/registry_spec.rb: page derivation + overrides, all/grouped over
  page entries, view_class resolution, href, icon, nav_items (authored-only),
  view_namespace-unset, mixed-mode error.
- spec/docs_kit/configuration_spec.rb: nav_registries default/override, nav_groups
  derivation, empty-group drop, explicit-nav-wins, empty fallback.
- spec/generators/page_generator_spec.rb: compact class + constants, v2 injection
  + ordering, --slug/--view/--eyebrow/--registry, legacy no-mutation, idempotence.
- Configuration + Registry at 100% line coverage.

## Verification
- [x] bundle exec rake (rspec 153 examples 0 failures + rubocop clean)
- [x] Dogfood smoke: `rails g docs_kit:page "Smoke Test" --group=Guide` → page
      renders at /docs/smoke-test, in sidebar; reverted.
- [x] All dogfood pages render 200 with the derived sidebar; URLs preserved.
@mhenrixon mhenrixon self-assigned this Jul 3, 2026
@mhenrixon mhenrixon added the enhancement New feature or request label Jul 3, 2026
@mhenrixon
mhenrixon merged commit 0e21329 into main Jul 3, 2026
3 checks passed
@mhenrixon
mhenrixon deleted the issue-13-docs-kit-page-generator branch July 4, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(generator): rails g docs_kit:page — page class + registry entry in one command feat(registry): one-line page registration + auto-derived nav

1 participant